package simpleservlet;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;

import java.io.FileInputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

public class NettyTomcat {
    private final int port = 8080;
    private final String addr = "127.0.0.1";
    private ServerSocket serverSocket;
    private Map<String,Servlet> servletMapping = new HashMap<>();

    private Properties properties = new Properties();

    private void init(){
        //加载application，同时初始化ServeltMapping
        try {
            String WEB_INF = this.getClass().getResource("/").getPath();
            WEB_INF = URLDecoder.decode(WEB_INF,"UTF-8"); //个人路径有中文
            FileInputStream fileInputStream = new FileInputStream(WEB_INF + "application.properties");

            properties.load(fileInputStream);

            properties.keySet().stream().forEach(keySet -> {
                String key = keySet.toString();
                if(key.endsWith(".url")) {
                    String servletName = key.replaceAll("\\.url$","");
                    String url = properties.getProperty(key);

                    String className = properties.getProperty(servletName + ".class");

                    System.out.printf("%s---------%s---------%s",servletName,url,className);
                    Servlet obj = null;
                    try {
                        //单实例，多线程
                        obj = (Servlet) Class.forName(className).newInstance();
                    } catch (InstantiationException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }

                    servletMapping.put(url,obj);
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 启动容器
     * @throws Exception
     */
    public void start() throws Exception {
        init();
        //boss线程
        EventLoopGroup bossGroup = null;
        //worker线程
        EventLoopGroup workerGroup = null;
        try {
            bossGroup= new NioEventLoopGroup();
            workerGroup = new NioEventLoopGroup();

            //引导类
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup,workerGroup)
                    //主线程处理类
                    .channel(NioServerSocketChannel.class)
                    //绑定本机地址
                    .localAddress(new InetSocketAddress(addr,port))
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            //http 响应编码器
                            socketChannel.pipeline().addLast(new HttpResponseEncoder());
                            //http请求解码器
                            socketChannel.pipeline().addLast(new HttpRequestDecoder());
                            //业务逻辑处理器
                            socketChannel.pipeline().addLast(new TomcatHandler(servletMapping));
                        }
                    }).option(ChannelOption.SO_BACKLOG,128) //主线程最大线程数128
                    .childOption(ChannelOption.SO_KEEPALIVE,true); //保持长链接

            //启动服务器
            ChannelFuture f = bootstrap.bind().sync();
            System.out.println("netty 版tomcat已启动");
            f.channel().closeFuture().sync();
        }catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭线程池
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }




    //启动容器
    public static void main(String[] args) throws Exception {
        new NettyTomcat().start();
    }
}
